# 导入numpy库
import numpy as np
import cupy as cp
# 定义一个一维模糊k-means类
class FuzzyKMeans:

    # 初始化方法，接受聚类数目和数据作为参数
    def __init__(self, knum, data):
        self.knum = knum # 聚类数目
        self.data = data # 数据
        self.n = len(data) # 数据个数
        self.m = 2 # 模糊指数，一般取2
        self.max_iter = 100 # 最大迭代次数
        self.tol = 1e-4 # 收敛判据
        self.centers = None # 聚类中心
        self.membership = None # 隶属度矩阵

    # 计算两个一维点之间的距离
    def distance(self, x, y):
        return abs(x - y)
    def power(self,x,y):
        if x==0:
               return 1
        else:
            return pow(float(x),y)
    # 计算隶属度矩阵
    def update_membership(self):
        # 初始化隶属度矩阵为零矩阵
        self.membership = np.zeros((self.n, self.knum))
        # 遍历每个数据点
        for i in range(self.n):
            # 遍历每个聚类中心
            for j in range(self.knum):
                # 计算分子，即当前聚类中心到数据点的距离的负m次方
                numerator = self.power(self.distance(self.data[i], self.centers[j]),-self.m)
                # 计算分母，即所有聚类中心到数据点的距离的负m次方之和
                denominator = 0
                for k in range(self.knum):
                    denominator += self.power(self.distance(self.data[i], self.centers[k]),(-self.m))
                # 计算隶属度，即分子除以分母
                self.membership[i][j] = numerator / denominator

    # 计算聚类中心
    def update_centers(self):
        # 初始化聚类中心为零数组
        self.centers = np.zeros(self.knum)
        # 遍历每个聚类中心
        for j in range(self.knum):
            # 计算分子，即所有数据点的隶属度的m次方乘以数据点之和
            numerator = 0
            for i in range(self.n):
                numerator += self.membership[i][j] ** self.m * self.data[i]
            # 计算分母，即所有数据点的隶属度的m次方之和
            denominator = 0
            for i in range(self.n):
                denominator += self.membership[i][j] ** self.m
            # 计算聚类中心，即分子除以分母
            self.centers[j] = numerator / denominator

    # 计算目标函数，即误差平方和
    def getsse(self):
        # 初始化目标函数为零
        sse = 0
        # 遍历每个数据点
        for i in range(self.n):
            # 遍历每个聚类中心
            for j in range(self.knum):
                # 累加隶属度的m次方乘以数据点到聚类中心的距离的平方
                sse += self.membership[i][j] ** self.m * self.distance(self.data[i], self.centers[j]) ** 2
        # 返回目标函数
        return sse

    # 聚类方法
    def fit(self):
        # 随机初始化聚类中心
        self.centers = np.random.choice(self.data, self.knum)
        # 更新隶属度矩阵
        self.update_membership()
        # 更新聚类中心
        self.update_centers()
if __name__ == "__main__":
        data=np.array([1,5,4,6,9,102,45])
        a=FuzzyKMeans(2,data)
        print(a.centers)
        a.fit()
        print(a.centers)
        a.fit()
        print(a.centers)
        #print(a.labels)
        print(a.getsse())
